package com.bicntech.common.core.controller;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bicntech.common.utils.ServletUtils;
import com.bicntech.common.utils.sql.SqlUtil;
import lombok.Data;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

/**
 * @author lan
 */
public abstract class SuperController {


    protected <T> Page<T> packPage() {
        return PageTool.packagePageVal();
    }


    @InitBinder    /* Converts empty strings into null when a form is submitted */
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new NullStringAsNullEditor());
    }


    private static class NullStringAsNullEditor extends StringTrimmerEditor {
        public NullStringAsNullEditor() {
            super(true);
        }

        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            if ("null".equals(text) || "undefined".equals(text)) {
                this.setValue(null);
            } else {
                super.setAsText(text);
            }
        }
    }


    static final class PageTool {

        static final OrderItem default_order_item = new OrderItem("id", false);

        public static <T> Page<T> packagePageVal() {
            int page = toInt(ServletUtils.getParameter("pageNum"), 1);
            int limit = toInt(ServletUtils.getParameter("pageSize"), 10);
            String orderBy = ServletUtils.getParameter("orderBy");
            String isAsc = ServletUtils.getParameter("isAsc");
            return toPage(new PageVal(page, limit, orderBy, isAsc));
        }


        @Data
        static class PageVal {
            private int pageNo;
            private int pageSize;
            private String orderBy;
            private Boolean isAsc;

            public PageVal(Integer pageNo, Integer pageSize, String orderBy, String isAsc) {
                this.pageNo = pageNo;
                this.pageSize = pageSize;
                this.orderBy = orderBy;
                this.isAsc = BooleanUtil.toBoolean(isAsc);
            }
        }

        private static <T> Page<T> toPage(@NonNull PageVal pageVal) {
            if (pageVal.pageNo <= 0)
                pageVal.pageNo = 1;
            if (pageVal.pageSize <= 0 || pageVal.pageSize > 100)
                pageVal.pageSize = 100;
            Page<T> page = new Page<T>(pageVal.getPageNo(), pageVal.getPageSize());
            String orderBy = StrUtil.toUnderlineCase(pageVal.orderBy);

            if (StringUtils.isNotBlank(orderBy) && SqlUtil.isValidOrderBySql(orderBy)) {
                return page.addOrder(new OrderItem(orderBy, pageVal.isAsc));
            }
            return page;
        }
    }

    /**
     * 转换为int<br>
     * 如果给定的值为空，或者转换失败，返回默认值<br>
     * 转换失败不会报错
     *
     * @param value        被转换的值
     * @param defaultValue 转换错误时的默认值
     * @return 结果
     */
    public static Integer toInt(Object value, Integer defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof Integer) {
            return (Integer) value;
        }
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(valueStr.trim());
        } catch (Exception e) {
            return defaultValue;
        }
    }

    public static String toStr(Object value, String defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        if (value instanceof String) {
            return (String) value;
        }
        return value.toString();
    }
}
